package com.atguigu.java2;

/**
 * 线程通信的列子：使用两个线程打印 1-100.线程1，线程2交替通信
 *
 * 涉及到线程通信的三个方法
 * wait():一旦执行此方法，当前线程就进入阻塞状态，并释放同步监视器
 * notify():一旦执行此方法，就会唤醒被wait的一个线程。如果有多个线程被wait，就唤醒优先级高的线程
 * notifyAll():一旦执行此方法，就会唤醒所有被wait的线程。
 *
 * 说明：
 * 1.wait(),notify(),notifyAll()三个方法必须使用在同步代码块或者同步方法之中。
 * 2.wait(),notify(),notifyAll()三个方法的调用者，必须是同步代码块或者同步方法中的同步监视器。
 *  否则，会出现异常。
 * 3..wait(),notify(),notifyAll()三个方法是定义在java.lang.object类下的
 * 面试题：sleep（）和wait（）方法的异同
 * 1、相同点：一旦执行此方法，都可以使当前的线程进入阻塞状态
 * 2、不同点：1），两个方法声明的位置不一样，Thread类中声明sleep。Object类中声明wait
 *           2），调用的要求不一样，sleep可以在任何场景下调用，wait必须使用在同步代码块或者同步方法中
 *           3），关于是否释放同步监视器的问题。如果两个方法都使用在同步代码块或者同步方法中，sleep不会释放同步监视器，wait会释放同步监视器
 */

class Communication implements Runnable {

    private int number = 1;

    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                //唤醒线程
                notify();
                if (number < 100) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;

                    try {
                        //使得调用如下wait（）方法的线程进入阻塞状态
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
}
public class CommunicationTest {

    public static void main(String[] args) {
        Communication c = new Communication();
        Thread t1 = new Thread(c);
        Thread t2 = new Thread(c);

        t1.setName("线程1：");
        t2.setName("线程2：");

        t1.start();
        t2.start();
    }



}
